import { CellEditor, CellValue, Column, ValidationResult } from '../types'

export abstract class BaseEditor implements CellEditor {
  protected container: HTMLElement | null = null
  protected column: Column
  protected originalValue: CellValue
  protected element: HTMLElement | null = null
  
  // 值变化回调
  onValueChange?: (value: CellValue) => void
  
  constructor(column: Column) {
    this.column = column
    this.originalValue = null
  }
  
  create(container: HTMLElement, value: CellValue, column: Column): void {
    this.container = container
    this.column = column
    this.originalValue = value
    
    // 创建编辑器元素
    this.element = this.createElement(value)
    
    // 应用通用样式
    this.applyStyles()
    
    // 添加事件监听
    this.attachEventListeners()
    
    // 添加到容器
    container.appendChild(this.element)
  }
  
  // 子类必须实现的方法
  protected abstract createElement(value: CellValue): HTMLElement
  
  // 获取值的默认实现
  abstract getValue(): CellValue
  
  // 设置值
  abstract setValue(value: CellValue): void
  
  // 应用样式
  protected applyStyles(): void {
    if (!this.element) return
    
    // 基础样式
    this.element.style.cssText = `
      width: 100%;
      height: 100%;
      border: 2px solid #3b82f6;
      outline: none;
      padding: 0 8px;
      font-size: 13px;
      font-family: inherit;
      box-sizing: border-box;
      background: white;
      border-radius: 4px;
      transition: border-color 0.2s;
    `
    
    // 自定义样式
    this.applyCustomStyles()
  }
  
  // 子类可以覆盖以应用自定义样式
  protected applyCustomStyles(): void {
    // 子类实现
  }
  
  // 添加事件监听器
  protected attachEventListeners(): void {
    if (!this.element) return
    
    // 键盘事件
    this.element.addEventListener('keydown', this.handleKeyDown.bind(this))
    
    // 值变化事件
    this.element.addEventListener('input', this.handleInput.bind(this))
    
    // 子类可以添加更多事件
    this.attachCustomEventListeners()
  }
  
  // 子类可以覆盖以添加自定义事件
  protected attachCustomEventListeners(): void {
    // 子类实现
  }
  
  // 处理键盘事件
  protected handleKeyDown(e: KeyboardEvent): void {
    if (e.key === 'Escape') {
      // 恢复原始值
      this.setValue(this.originalValue)
    }
  }
  
  // 处理输入事件
  protected handleInput(e: Event): void {
    if (this.onValueChange) {
      this.onValueChange(this.getValue())
    }
  }
  
  // 验证
  validate(): ValidationResult {
    const value = this.getValue()
    
    // 必填验证
    const editOptions = this.getEditOptions()
    if (editOptions.required && (value === null || value === undefined || value === '')) {
      return { valid: false, message: '此字段为必填项' }
    }
    
    // 使用列的验证器
    if (this.column.validator) {
      return this.column.validator(value)
    }
    
    // 子类特定验证
    return this.customValidate(value)
  }
  
  // 子类可以覆盖以实现自定义验证
  protected customValidate(value: CellValue): ValidationResult {
    return { valid: true }
  }
  
  // 获取编辑选项
  protected getEditOptions(): any {
    if (typeof this.column.editOptions === 'object' && !Array.isArray(this.column.editOptions)) {
      return this.column.editOptions
    }
    return {}
  }
  
  // 聚焦
  focus(): void {
    if (this.element && 'focus' in this.element) {
      (this.element as any).focus()
      
      // 如果是输入框，选中文本
      if ('select' in this.element) {
        (this.element as any).select()
      }
    }
  }
  
  // 销毁
  destroy(): void {
    if (this.element && this.element.parentNode) {
      this.element.parentNode.removeChild(this.element)
    }
    this.element = null
    this.container = null
  }
  
  // 工具方法
  protected formatDate(date: Date | null, format?: string): string {
    if (!date) return ''
    
    const year = date.getFullYear()
    const month = String(date.getMonth() + 1).padStart(2, '0')
    const day = String(date.getDate()).padStart(2, '0')
    const hours = String(date.getHours()).padStart(2, '0')
    const minutes = String(date.getMinutes()).padStart(2, '0')
    const seconds = String(date.getSeconds()).padStart(2, '0')
    
    switch (format) {
      case 'date':
        return `${year}-${month}-${day}`
      case 'time':
        return `${hours}:${minutes}:${seconds}`
      case 'datetime':
      default:
        return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
    }
  }
  
  protected parseDate(str: string): Date | null {
    if (!str) return null
    
    try {
      // 尝试多种格式
      const date = new Date(str)
      if (!isNaN(date.getTime())) {
        return date
      }
      
      // 尝试解析特定格式
      const patterns = [
        /^(\d{4})-(\d{2})-(\d{2})$/,
        /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/,
        /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})/
      ]
      
      for (const pattern of patterns) {
        const match = str.match(pattern)
        if (match) {
          return new Date(str)
        }
      }
    } catch (error) {
      console.error('Date parse error:', error)
    }
    
    return null
  }
} 